#include <iostream>
#include <vector>
#include <string>
#include <chrono>
#include "time_interval.h"

// g++ -std=c++14 emplace_class.cpp

class Foo {
public:
    Foo(std::string str) : name(str) {
        std::cout << name << " constructor" << std::endl;
    }
    Foo(const Foo& f) : name(f.name) {
        std::cout << "copy constructor" << std::endl;
    }
    Foo(Foo&& f) : name(std::move(f.name)){
        std::cout << "move constructor" << std::endl;
    }
    ~Foo(){
        // std::cout << name << " destructor.\n";
    }

private:
    std::string name;
};

class Fo {
public:
    Fo(std::string str) : name(str) {  }
    Fo(const Fo& f) : name(f.name) {
    }
    Fo(Fo&& f) : name(std::move(f.name)){
    }
    ~Fo(){}

private:
    std::string name;
};


int main() {


    std::vector<Fo> v;
    std::vector<Foo> v2;
    int count = 10000000;
    v.reserve(count);       //预分配1千万大小，排除掉分配内存的时间
    v2.reserve(10);


    auto get_milisec = [](auto& start){
        std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start).count() << "ms\n";
        // std::cout << std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - start).count() << "ms\n";
    };

    {
        std::cout << "v.push_back(obj): ";
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i < count; i++)
        {
            Fo temp("ceshi");
            v.push_back(temp);// push_back(const string&)，参数是左值引用
        }
        get_milisec(start);
    }

    v.clear();
    {
        std::cout << "v.emplace_back(obj): ";
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i < count; i++)
        {
            Fo temp("ceshi");
            v.emplace_back(temp);// push_back(const string&)，参数是左值引用
        }
        get_milisec(start);
    }

    v.clear();
    {
        std::cout << "v.push_back(std::move(obj)): ";
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i < count; i++)
        {
            Fo temp("ceshi");
            v.push_back(std::move(temp));// push_back(string &&), 参数是右值引用
        }
        get_milisec(start);
    }

    v.clear();
    {
        std::cout << "v.emplace_back(std::move(obj)): ";
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i < count; i++)
        {
            Fo temp("ceshi");
            v.emplace_back(std::move(temp));// push_back(string &&), 参数是右值引用
        }
        get_milisec(start);
    }

    v.clear();
    {
        std::cout << "v.push_back(Obj()): ";
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i < count; i++)
        {
            v.push_back(Fo("ceshi"));// push_back(string &&), 参数是右值引用
        }
        get_milisec(start);
    }

    v.clear();
    {
        std::cout << "v.emplace_back(Obj()): ";
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i < count; i++)
        {
            v.emplace_back(Fo("ceshi"));// push_back(string &&), 参数是右值引用
        }
        get_milisec(start);
    }

    /////////////////////////////////////////////////////////////////////////////
    std::cout << "\n";
    {
        TIME_INTERVAL_SCOPE("push_back T:");
        Foo temp("ceshi");
        v2.push_back(temp);// push_back(const T&)，参数是左值引用
        //打印结果：
        //constructor
        //copy constructor
    }

    v2.clear();
    {
        TIME_INTERVAL_SCOPE("emplace_back(T):");
        Foo temp("ceshi");
        v2.emplace_back(temp);// push_back(T &&), 参数是右值引用
        //打印结果：
        //constructor
        //move constructor
    }

    v2.clear();
    {
        TIME_INTERVAL_SCOPE("push_back move(T):");
        Foo temp("ceshi");
        v2.push_back(std::move(temp));// push_back(T &&), 参数是右值引用
        //打印结果：
        //constructor
        //move constructor
    }

    v2.clear();
    {
        TIME_INTERVAL_SCOPE("emplace_back move(T):");
        Foo temp("ceshi");
        v2.emplace_back(std::move(temp));// push_back(T &&), 参数是右值引用
        //打印结果：
        //constructor
        //move constructor
    }

    v2.clear();
    {
        TIME_INTERVAL_SCOPE("push_back(T&&):");
        v2.push_back(Foo("ceshi"));// push_back(T &&), 参数是右值引用
        //打印结果：
        //constructor
        //move constructor
    }

    v2.clear();
    {
        TIME_INTERVAL_SCOPE("emplace_back(T&&):");
        v2.emplace_back(Foo("ceshi"));// 只有一次构造函数，不调用拷贝构造函数，速度最快
        //打印结果：
        //constructor
    }
}